/* 
 * PROJECT: MMD for Java
 * --------------------------------------------------------------------------------
 * This work is based on the ARTK_MMD v0.1 
 *   PY
 * http://ppyy.hp.infoseek.co.jp/
 * py1024<at>gmail.com
 * http://www.nicovideo.jp/watch/sm7398691
 *
 * The MMD for Java is Java version MMD class library.
 * Copyright (C)2009 nyatla
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this framework; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * For further information please contact.
 *	http://nyatla.jp/
 *	<airmail(at)ebony.plala.or.jp>
 * 
 */
package jp.nyatla.nymmd.types;


public class MmdVector4
{
	public double x, y, z, w;		
	public void setValue(MmdVector4 v)
	{
		this.x=v.x;
		this.y=v.y;
		this.z=v.z;
		this.w=v.w;
		return;
	}	
	public void QuaternionSlerp(MmdVector4 pvec4Src1,MmdVector4 pvec4Src2, double fLerpValue )
	{

		// Qlerp
		double	qr = pvec4Src1.x * pvec4Src2.x + pvec4Src1.y * pvec4Src2.y + pvec4Src1.z * pvec4Src2.z + pvec4Src1.w * pvec4Src2.w;
		double	t0 = 1.0f - fLerpValue;

		if( qr < 0 )
		{
			this.x = pvec4Src1.x * t0 - pvec4Src2.x * fLerpValue;
			this.y = pvec4Src1.y * t0 - pvec4Src2.y * fLerpValue;
			this.z = pvec4Src1.z * t0 - pvec4Src2.z * fLerpValue;
			this.w = pvec4Src1.w * t0 - pvec4Src2.w * fLerpValue;
		}
		else
		{
			this.x = pvec4Src1.x * t0 + pvec4Src2.x * fLerpValue;
			this.y = pvec4Src1.y * t0 + pvec4Src2.y * fLerpValue;
			this.z = pvec4Src1.z * t0 + pvec4Src2.z * fLerpValue;
			this.w = pvec4Src1.w * t0 + pvec4Src2.w * fLerpValue;
		}
		QuaternionNormalize(this);
		return;
	}
	public void QuaternionNormalize(MmdVector4 pvec4Src)
	{
		final double fSqr =1.0 / Math.sqrt(( pvec4Src.x * pvec4Src.x + pvec4Src.y * pvec4Src.y + pvec4Src.z * pvec4Src.z + pvec4Src.w * pvec4Src.w));

		this.x =(pvec4Src.x * fSqr);
		this.y =(pvec4Src.y * fSqr);
		this.z =(pvec4Src.z * fSqr);
		this.w =(pvec4Src.w * fSqr);
	}
	public void QuaternionCreateAxis(MmdVector3 pvec3Axis, double fRotAngle )
	{
		if( Math.abs( fRotAngle ) < 0.0001f )
		{
			this.x = this.y = this.z = 0.0f;
			this.w = 1.0f;
		}
		else
		{
			fRotAngle *= 0.5f;
			double	fTemp = Math.sin(fRotAngle);

			this.x = pvec3Axis.x * fTemp;
			this.y = pvec3Axis.y * fTemp;
			this.z = pvec3Axis.z * fTemp;
			this.w = Math.cos( fRotAngle );
		}
		return;
	}
	public void QuaternionMultiply(MmdVector4 pvec4Src1,MmdVector4 pvec4Src2)
	{
		double	px, py, pz, pw;
		double	qx, qy, qz, qw;

		px = pvec4Src1.x; py = pvec4Src1.y; pz = pvec4Src1.z; pw = pvec4Src1.w;
		qx = pvec4Src2.x; qy = pvec4Src2.y; qz = pvec4Src2.z; qw = pvec4Src2.w;

		this.x = pw * qx + px * qw + py * qz - pz * qy;
		this.y = pw * qy - px * qz + py * qw + pz * qx;
		this.z = pw * qz + px * qy - py * qx + pz * qw;
		this.w = pw * qw - px * qx - py * qy - pz * qz;
	}
	public void QuaternionCreateEuler(MmdVector3 pvec3EulerAngle )
	{
		final double	xRadian = pvec3EulerAngle.x * 0.5;
		final double	yRadian = pvec3EulerAngle.y * 0.5;
		final double	zRadian = pvec3EulerAngle.z * 0.5;
		final double	sinX = Math.sin( xRadian );
		final double	cosX = Math.cos( xRadian );
		final double	sinY = Math.sin( yRadian );
		final double	cosY = Math.cos( yRadian );
		final double	sinZ = Math.sin( zRadian );
		final double	cosZ = Math.cos( zRadian );

		// XYZ
		this.x = sinX * cosY * cosZ - cosX * sinY * sinZ;
		this.y = cosX * sinY * cosZ + sinX * cosY * sinZ;
		this.z = cosX * cosY * sinZ - sinX * sinY * cosZ;
		this.w = cosX * cosY * cosZ + sinX * sinY * sinZ;
	}
	
}
